use std::io;
use rand::Rng;
use std::cmp::Ordering;

/*
fn memory_alloca() {
    let s1 = String::from("wanghongfucoder");
//    ERROR use s1
    // let s2 = s1;
//     println!("{},world", s1);
    let s2 = s1.clone();
    println!("{}--> {}",s1, s2);
} */
#[derive(Debug)]
struct User{
    username: String,
    email: String,
    sign_in_count: u64,
    active: bool,
}

impl User{
    fn say_hello(&self) {
        println!("{} say hello to you!! \n", self.username);
    }
}

fn guest_game() {
    println!("Guess the number!");
    let secret_number = rand::thread_rng().gen_range(1..101);
    println!("The secret number is: {}", secret_number);
    loop {
        println!("Please input your guess.");
        let mut guess = String::new();
        io::stdin().read_line(&mut guess).expect("Failed to read line");
        // let guess: u32 = guess.trim().parse().expect("Please type a number");
        let guess: u32 = match guess.trim().parse() {
            Ok(num) => num,
            Err(_) => continue,
        };
        println!("You guessed: {}", guess);
        match guess.cmp(&secret_number) {
            Ordering::Equal => {
                println!("You win!");
                break;
            }
            Ordering::Greater => println!("Too big"),
            Ordering::Less => println!("Too small"),
        }
    }
}

fn gives_ownership() -> String{
    let some_string = String::from("wanghongfucoder");
    some_string
}

fn takes_and_give_back(a_string: String) -> String{
    a_string
}

fn move_value() {
    let s1 = gives_ownership();
    println!("s1--> {}", s1);
    let s2 = String::from("haha");
    println!("s2 -->{}", s2);
    let s3 = takes_and_give_back(s2);
    // s2 has been moved
    println!("{}", s3);
}

fn calculate_length(s:String) -> (String, usize) {
    let length = s.len();
    (s, length)
}

fn tup_move_example() {
    let s1 = String::from("lalalalalalal");
    let (s2, len) = calculate_length(s1);
    println!("s1 --> {}  len -->{}", s2, len);
}

fn calculate_length2(s: &String) -> usize {
    s.len()
}

//  slice example

fn first_word(s: &String) -> &str {
    let bytes = s.as_bytes();
    for (i, &item) in bytes.iter().enumerate() {
        if item == b' '{
            return &s[0..i]
        }
    }
    &s[..]
}

fn slice_example() {
    let mut str1 = String::from("haha wang");
    let word = first_word(&str1);
    println!("word --> {}", word);
    println!("str1 --> {}", str1);
    // str1.clear();
    // println!("after clear word -->{}", word);
}

fn  reference_example() {
    let s1 = String::from("lalalalalalal");
    let len = calculate_length2(&s1);
    println!("s1 --> {}  len -->{}", s1, len);
}

fn struct_example() {
    let mut user1 = User{
        email: String::from("1583505981@qq.com"),
        username: String::from("wanghongfucoder"),
        active : true,
        sign_in_count :1,
    };
    user1.email = String::from("haha@qq.com");
    println!("email -- >{}", user1.email);
    let user2 = User {
        email: String::from("haha@qq.com"),
        username: String::from("dsa"),
        ..user1
    };
    println!("user1 -- >{:#?}", user2);
    user2.say_hello();
}

// field initialize sample way
fn build_user(email: String, username: String) -> User {
    User {
        email,
        username,
        active: true,
        sign_in_count: 1,
    }
}

#[derive(Debug)]
enum UsState{
    Alabama,
    Alaska,
}
enum Coin{
    Penny,
    Nickel,
    Dime,
    Quarter(UsState),
}

fn value_in_cents(coin: Coin) -> u8 {
    match coin {
        Coin::Penny =>1,
        Coin::Nickel =>5,
        Coin::Dime =>10,
        Coin::Quarter(state) =>{
            println!("State Quarter from {:?}!", state);
            25
        },
    }
}

fn plus_one(x: Option<i32>) -> Option<i32> {
    match x {
        None => None,
        Some(i) => Some(i +1)
    }
}

fn main() {
    // guest_game();
    // memory_alloca();
    // move_value();
    // tup_move_example();
    // reference_example();
    // slice_example();
    // struct_example();
    let five = Some(5);
    let six = plus_one(five);
    println!("{:?}", six);
    let none = plus_one(None);
}
